package com.loong.system.controller;

import cn.dev33.satoken.annotation.SaIgnore;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.loong.framework.dto.IdParamDTO;
import com.loong.framework.exception.RRException;
import com.loong.framework.utils.FileUploadUtil;
import com.loong.framework.utils.SystemUtil;
import com.loong.system.dto.FileAddDTO;
import com.loong.system.dto.FileUpdateDTO;
import com.loong.system.entity.File;
import com.loong.system.service.IFileService;
import com.loong.system.vo.FileDetailVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import java.io.IOException;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.thciwei.x.file.storage.core.FileInfo;
import org.thciwei.x.file.storage.core.FileStorageService;

@Slf4j
@Tag(name = "文件操作 API")
@RestController
@RequestMapping("/api/v1.0/file")
public class FileController {

  @Resource private FileStorageService fileStorageService;
  @Resource private IFileService fileService;

  @SaIgnore
  @Operation(summary = "上传文件，成功返回文件信息")
  @PostMapping("/upload")
  public FileInfo upload(MultipartFile file) {
    FileInfo upload;
    if (FileUploadUtil.isImageFile(file)) {
      upload = fileStorageService.of(file).setPlatform(SystemUtil.detectOS()).thumbnail().upload();
    } else {
      upload = fileStorageService.of(file).setPlatform(SystemUtil.detectOS()).upload();
    }

    if (upload == null) {
      throw new RRException("上传失败");
    }
    fileService.save(upload);
    return upload;
  }

  @SaIgnore
  @Operation(summary = "上传七牛云")
  @PostMapping("/uploadQiNiu")
  public FileInfo uploadQiNiu(MultipartFile file) {
    FileInfo qiniu;
    // 使用指定的存储平台
    qiniu =
        fileStorageService
            .of(file)
            .setPlatform("qiniu") // 使用指定的存储平台
            .upload();
    return qiniu;
  }

  @SaIgnore
  @Operation(summary = "预览原图")
  @GetMapping("preview/{id}")
  public void preview(@PathVariable("id") String id, HttpServletResponse response)
      throws JsonProcessingException {
    String openStyle = "inline";
    getFile(new IdParamDTO(id), response, openStyle, false);
  }

  @SaIgnore
  @Operation(summary = "预览缩略图")
  @GetMapping("previewThumbnail/{id}")
  public void previewThumbnail(@PathVariable("id") String id, HttpServletResponse response)
      throws JsonProcessingException {
    // Set the open style to inline.
    String openStyle = "inline";

    // Get the file with the specified ID and send it as a response.
    getFile(new IdParamDTO(id), response, openStyle, true);
  }

  @SaIgnore
  @Operation(summary = "下载文件")
  @GetMapping("download/{id}")
  public void download(@PathVariable("id") String id, HttpServletResponse response) {
    String openStyle = "attachment";
    try {
      getFile(new IdParamDTO(id), response, openStyle, false);
    } catch (Exception e) {
      log.error("文件下载失败", e);
    }
  }

  @Operation(summary = "新增")
  @PostMapping("/add")
  public void add(@RequestBody @Valid FileAddDTO addDTO) {
    File file = SystemUtil.buildResource(addDTO, File.class);
    fileService.save(file);
  }

  @Operation(summary = "删除")
  @PostMapping("/remove")
  public void remove(@RequestBody @Valid IdParamDTO idParamDTO) {
    fileService.removeById(idParamDTO.getId());
  }

  @Operation(summary = "更新")
  @PostMapping("/update")
  public void update(@RequestBody @Valid FileUpdateDTO updateDTO) {
    File file = SystemUtil.buildResource(updateDTO, File.class);
    fileService.updateById(file);
  }

  @Operation(summary = "详情")
  @PostMapping("/detail")
  public FileDetailVO detail(@RequestBody @Valid IdParamDTO idParamDTO) {
    File file = fileService.getById(idParamDTO.getId());
    return SystemUtil.buildResource(file, FileDetailVO.class);
  }

  private void getFile(
      @RequestBody @Valid IdParamDTO idParamDTO,
      HttpServletResponse response,
      String openStyle,
      boolean isThumb)
      throws JsonProcessingException {
    FileInfo fileInfo = fileService.getByIdItem(idParamDTO.getId());

    // 获取 InputStream 手动处理
    fileStorageService
        .download(fileInfo)
        .inputStream(
            in -> {
              response.setHeader(
                  "content-disposition",
                  openStyle
                      + ";filename="
                      + response.encodeURL(
                          isThumb ? fileInfo.getThFilename() : fileInfo.getFilename()));
              // 获取响应response输出流
              ServletOutputStream os;
              try {
                os = response.getOutputStream();
              } catch (IOException e) {
                throw new RuntimeException(e);
              }
              // 文件拷贝
              try {
                IOUtils.copy(in, os);
              } catch (IOException e) {
                throw new RuntimeException(e);
              }
              IOUtils.closeQuietly(in);
              IOUtils.closeQuietly(os);
            });
  }
}
